# EasyHook项目 - 支持生成静态库和Demo应用
cmake_minimum_required(VERSION 3.10)
project(EasyHookProject)

set(CMAKE_CXX_STANDARD 17)

# 设置为Release模式但保持可调试
set(CMAKE_BUILD_TYPE Release)

# MSVC编译器设置
if(MSVC)
    add_compile_options(/utf-8)
    add_compile_options(/wd4819)
    add_compile_options(/MP)
    add_compile_options(/Od)    # 禁用优化便于调试
    add_compile_options(/Zi)    # 生成调试信息
    
    # 修复类型转换警告
    add_compile_options(/wd4244) # 禁用从uintptr_t到DWORD的转换警告
    
    set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG")
    set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/DEBUG")
endif()

# MinHook 路径设置
set(MINHOOK_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/minhook")

# 根据架构选择合适的库
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
    set(MINHOOK_LIB_DIR "${MINHOOK_ROOT}/lib")
    set(MINHOOK_LIB_NAME "MinHook.x64")
    message(STATUS "Building for x64 architecture")
else()
    set(MINHOOK_LIB_DIR "${MINHOOK_ROOT}/lib")
    set(MINHOOK_LIB_NAME "MinHook.x86")
    message(STATUS "Building for x86 architecture")
endif()

# 检查MinHook是否存在
if(NOT EXISTS "${MINHOOK_ROOT}/include/MinHook.h")
    message(FATAL_ERROR "MinHook.h not found at ${MINHOOK_ROOT}/include/MinHook.h")
endif()

if(NOT EXISTS "${MINHOOK_LIB_DIR}/${MINHOOK_LIB_NAME}.lib")
    message(FATAL_ERROR "MinHook library not found at ${MINHOOK_LIB_DIR}/${MINHOOK_LIB_NAME}.lib")
endif()

# 包含目录
include_directories("${MINHOOK_ROOT}/include")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")

# ============================================
# 构建选项：选择使用哪种实现方式
# ============================================

option(BUILD_STATIC_LIB "Build EasyHook as static library" ON)
option(BUILD_HEADER_ONLY_DEMO "Build header-only demo" OFF)
option(BUILD_LIBRARY_DEMO "Build demo using static library" ON)

# ============================================
# 1. 构建EasyHook静态库 (使用EasyHookLib.cpp)
# ============================================

if(BUILD_STATIC_LIB)
    # 检查所需文件是否存在
    if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/EasyHookLib.cpp")
        message(FATAL_ERROR "EasyHookLib.cpp not found")
    endif()
    
    if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/EasyHookLib.h")
        message(FATAL_ERROR "EasyHookLib.h not found")
    endif()
    
    if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/EasyHookLib.inl")
        message(FATAL_ERROR "EasyHookLib.inl not found")
    endif()

    # 创建静态库
    add_library(EasyHookLib STATIC
        EasyHookLib.cpp
        EasyHookLib.h
        EasyHookLib.inl
    )

    # 设置库的编译定义
    target_compile_definitions(EasyHookLib PRIVATE
        _CRT_SECURE_NO_WARNINGS
        WIN32_LEAN_AND_MEAN
    )

    # 链接MinHook到静态库
    target_link_libraries(EasyHookLib 
        "${MINHOOK_LIB_DIR}/${MINHOOK_LIB_NAME}.lib"
    )

    # 设置库的包含目录
    target_include_directories(EasyHookLib PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}"
        "${MINHOOK_ROOT}/include"
    )

    # 设置库输出目录
    set_target_properties(EasyHookLib PROPERTIES
        ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
        ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib"
        ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib"
    )

    message(STATUS "EasyHookLib.lib will be generated in: ${CMAKE_BINARY_DIR}/lib/")
endif()

# ============================================
# 2. 构建使用静态库的Demo应用
# ============================================

if(BUILD_LIBRARY_DEMO AND BUILD_STATIC_LIB)
    if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
        # 创建使用静态库的可执行文件
        add_executable(EasyHookDemo main.cpp)

        # 设置目标属性
        target_compile_definitions(EasyHookDemo PRIVATE
            _CRT_SECURE_NO_WARNINGS
            WIN32_LEAN_AND_MEAN
        )

        # 链接EasyHook静态库
        target_link_libraries(EasyHookDemo 
            EasyHookLib
        )

        # 设置调试工作目录
        set_target_properties(EasyHookDemo PROPERTIES
            VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
        )

        message(STATUS "EasyHookDemo (using static lib) will be built")
    else()
        message(WARNING "main.cpp not found, skipping demo build")
    endif()
endif()

# ============================================
# 3. 构建Header-Only版本的Demo (可选)
# ============================================

if(BUILD_HEADER_ONLY_DEMO)
    if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/EasyHook.h")
        # 创建使用Header-Only版本的可执行文件
        add_executable(EasyHookDemo_HeaderOnly main.cpp)

        # 设置目标属性
        target_compile_definitions(EasyHookDemo_HeaderOnly PRIVATE
            _CRT_SECURE_NO_WARNINGS
            WIN32_LEAN_AND_MEAN
            EASYHOOK_HEADER_ONLY  # 可以在代码中用这个宏来区分版本
        )

        # 直接链接MinHook库 (Header-Only版本)
        target_link_libraries(EasyHookDemo_HeaderOnly 
            "${MINHOOK_LIB_DIR}/${MINHOOK_LIB_NAME}.lib"
        )

        # 设置调试工作目录
        set_target_properties(EasyHookDemo_HeaderOnly PROPERTIES
            VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
        )

        message(STATUS "EasyHookDemo_HeaderOnly will be built")
    else()
        message(WARNING "main.cpp or EasyHook.h not found, skipping header-only demo")
    endif()
endif()

# ============================================
# 安装配置（可选）
# ============================================

if(BUILD_STATIC_LIB)
    # 安装库文件
    install(TARGETS EasyHookLib
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin
    )

    # 安装头文件
    install(FILES EasyHookLib.h EasyHookLib.inl
        DESTINATION include
    )
endif()

# ============================================
# 输出编译信息
# ============================================

message(STATUS "")
message(STATUS "=== Build Configuration ===")
message(STATUS "Project: ${PROJECT_NAME}")
message(STATUS "C++ Standard: ${CMAKE_CXX_STANDARD}")
message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
message(STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "")
message(STATUS "=== Build Options ===")
message(STATUS "BUILD_STATIC_LIB: ${BUILD_STATIC_LIB}")
message(STATUS "BUILD_HEADER_ONLY_DEMO: ${BUILD_HEADER_ONLY_DEMO}")
message(STATUS "BUILD_LIBRARY_DEMO: ${BUILD_LIBRARY_DEMO}")
message(STATUS "")
message(STATUS "=== Output Files ===")
if(BUILD_STATIC_LIB)
    message(STATUS "Static Library: ${CMAKE_BINARY_DIR}/lib/EasyHookLib.lib")
endif()
if(BUILD_LIBRARY_DEMO AND BUILD_STATIC_LIB)
    message(STATUS "Demo Executable: ${CMAKE_BINARY_DIR}/EasyHookDemo.exe")
endif()
if(BUILD_HEADER_ONLY_DEMO)
    message(STATUS "Header-Only Demo: ${CMAKE_BINARY_DIR}/EasyHookDemo_HeaderOnly.exe")
endif()
message(STATUS "")

# ============================================
# 添加清理目标
# ============================================

add_custom_target(clean-all
    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target clean
    COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/CMakeFiles
    COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/lib
    COMMENT "Cleaning all build files"
)
